<script lang="ts" setup>
import { computed, onMounted, reactive, ref } from "vue";
import { MachineSelect } from "@/components/business";
import api from "@/api";
import { type MachineGroupDTO, MachineSaveCmd, MachineType } from "@/types";
import { ElMessage, type FormInstance, type FormRules } from "element-plus";

const emit = defineEmits(["success"]);

interface State {
  visible: boolean;
  form: MachineSaveCmd;
  machineGroupList: MachineGroupDTO[];
}

const fileRef = ref<HTMLInputElement | null>(null);

const state = reactive<State>({
  visible: false,
  form: new MachineSaveCmd(),
  machineGroupList: []
});

const formRef = ref<FormInstance | null>(null);

const rules: FormRules<MachineSaveCmd> = {
  name: [{ required: true, message: "请输入", trigger: ["blur", "change"] }],
  groupId: [{ required: true, message: "请选择", trigger: ["blur", "change"] }],
  ip: [
    { required: true, message: "请输入", trigger: ["blur", "change"] },
    {
      pattern:
        /^((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))$/,
      message: "ip格式不正确",
      trigger: ["blur", "change"]
    }
  ],
  port: [
    { required: true, message: "请输入", trigger: ["blur", "change"] },
    { pattern: /^[0-9]*$/, message: "请输入数字", trigger: ["blur", "change"] }
  ],
  username: [{ required: true, message: "请输入", trigger: ["blur", "change"] }],
  type: [{ required: true, message: "请选择", trigger: ["blur", "change"] }],
  password: [
    {
      validator: (rule, value, callback) => {
        if (state.form.type !== MachineType.Password) {
          callback();
          return;
        }
        if (!value || value.length == 0) {
          // 自定义验证条件，返回错误提示文字
          callback(new Error("请输入"));
        } else {
          callback();
        }
      },
      trigger: ["blur", "change"]
    }
  ],
  publicKey: [
    {
      validator: (rule, value, callback) => {
        if (state.form.type !== MachineType.PublicKey) {
          callback();
          return;
        }
        if (!value || value.length == 0) {
          // 自定义验证条件，返回错误提示文字
          callback(new Error("请输入"));
        } else {
          callback();
        }
      },
      trigger: ["blur", "change"]
    }
  ],
  isJump: [{ required: true, message: "请选择", trigger: ["blur", "change"] }],
  jumpMachineId: [
    {
      validator: (rule, value, callback) => {
        if (!state.form.isJump) {
          callback();
          return;
        }

        if (!value || value.length == 0) {
          // 自定义验证条件，返回错误提示文字
          callback(new Error("请选择"));
        } else {
          callback();
        }
      },
      trigger: ["blur", "change"]
    }
  ]
};

const title = computed(() => {
  return state.form.id ? "编辑主机" : "新建主机";
});

const submit = () => {
  formRef.value?.validate((valid, fields) => {
    if (valid) {
      api.machine.saveMachine(state.form).then((res) => {
        ElMessage.success(res.message);
        emit("success");
        state.visible = false;
      });
    }
  });
};

const reset = () => {
  state.form = new MachineSaveCmd();
  loadGroupList();
  formRef.value?.resetFields();
};

const loadGroupList = () => {
  api.machineGroup
    .getMachineGroupList({
      size: 1000,
      current: 1
    })
    .then((res) => {
      state.machineGroupList = res.data.data;
    });
};

const handleFileSwitch = () => {
  if (state.form.type === MachineType.Password) {
    state.form.publicKey = "";
  } else {
    state.form.password = "";
  }
  fileRef.value!.value = "";
  fileRef.value?.click();
};

const handleFileChange = (e: Event) => {
  const target = e.target as HTMLInputElement;
  const files = target.files;
  if (files) {
    const file = files[0];
    const reader = new FileReader();
    reader.onload = (e) => {
      state.form.publicKey = e.target?.result as string;
    };
    reader.readAsText(file);
  }
};

const openDialog = (id?: string) => {
  if (id) {
    api.machine.getMachine(id).then((r) => {
      state.form = r.data;
      console.log("openDialog => ", state.form);
    });
  }
  state.visible = true;
};

const closeDialog = () => {
  state.visible = false;
};

onMounted(() => {
  loadGroupList();
});

defineExpose({
  openDialog,
  closeDialog
});
</script>

<template>
  <el-dialog
    v-model="state.visible"
    :title="title"
    :close-on-click-modal="false"
    @open="reset"
    width="600"
  >
    <div>
      <el-form :model="state.form" label-width="auto" ref="formRef" :rules="rules">
        <el-form-item label="主机名称" prop="name">
          <el-input v-model="state.form.name" />
        </el-form-item>
        <el-form-item label="主机组：" prop="groupId">
          <el-select v-model="state.form.groupId" placeholder="请选择" clearable>
            <el-option
              v-for="item in state.machineGroupList"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="主机IP" prop="ip">
          <el-input v-model="state.form.ip" />
        </el-form-item>
        <el-form-item label="端口" prop="port">
          <el-input v-model="state.form.port" />
        </el-form-item>
        <el-form-item label="用户名" prop="username">
          <el-input v-model="state.form.username" />
        </el-form-item>

        <el-form-item label="类型" prop="type">
          <el-select v-model="state.form.type" placeholder="请选择">
            <el-option label="密码" :value="MachineType.Password" />
            <el-option label="公钥" :value="MachineType.PublicKey" />
          </el-select>
        </el-form-item>
        <el-form-item label="密码" prop="password" v-show="state.form.type === MachineType.Password">
          <el-input v-model="state.form.password" />
        </el-form-item>
        <el-form-item
          label="公钥"
          prop="publicKey"
          v-show="state.form.type === MachineType.PublicKey"
        >
          <div flex flex-row w-full gap-2 items-center>
            <el-input type="textarea" v-model="state.form.publicKey" />
            <el-button type="primary" @click="handleFileSwitch">选择文件</el-button>
          </div>
        </el-form-item>
        <el-form-item label="使用跳板机" prop="isJump">
          <el-radio-group v-model="state.form.isJump">
            <el-radio :value="true">使用</el-radio>
            <el-radio :value="false">不使用</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="选择跳板机" prop="jumpMachineId" v-show="state.form.isJump">
          <machine-select :id="state.form.jumpMachineId" v-model="state.form.jumpMachineId" />
        </el-form-item>
      </el-form>
      <input hidden type="file" ref="fileRef" @change="handleFileChange" />
    </div>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="state.visible = false">取消</el-button>
        <el-button type="primary" @click="submit"> 确认</el-button>
      </div>
    </template>
  </el-dialog>
</template>
